#!/bin/ksh
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
#  
#  
# Licensed Materials - Property of IBM 
#  
# (C) COPYRIGHT International Business Machines Corp. 2001,2002 
# All Rights Reserved 
#  
# US Government Users Restricted Rights - Use, duplication or 
# disclosure restricted by GSA ADP Schedule Contract with IBM Corp. 
#  
# IBM_PROLOG_END_TAG 
# @(#)89   1.15         src/rsct/cfg_access/cfghact.sh, cfg.access, rsct_rori, roris01a 5/20/02 20:58:44
#
# usage:
#   cfghact -i [-f] [-x] # after the 1st installation (-x no start)
#   cfghact -U [-x]	# before the upgrade (-x no start)
#   cfghact -u [-f]	# after the upgrade
#   cfghact -z [-x]	# before the uninstallation [-x no stop]
#   cfghact -d [-x]	# delete HATS/HAGS subsystems (incl. ConfigRM)
#   cfghact -c <clstname> -n <nodenum> [-f] [-w]
#			# change the cluster name
#
# note:
#   -f stop or restart rmc, and force to update if necessary
#   -x no start or stop (Network Installation)
#   -w wait until all rmc procs are stopped or restarted
#

PATH=/usr/sbin/rsct/install/bin:/usr/sbin/rsct/bin:/usr/bin:/bin:/usr/sbin:/sbin
export PATH

export MSGMAPPATH="/usr/sbin/rsct/msgmaps"
CATFILE=ha_com.cat
MSGCMD="/usr/sbin/rsct/bin/hadspmsg cfgaccess ${CATFILE}"

RSCTBIN=/usr/sbin/rsct/bin
CTROOT=/var/ct

# Link CCAL scripts to cfgmgr if not done already
CCAL_CMDS="ct_hats_info ct_hags_info ct_topology_info \
	   ct_read_machines_lst ct_write_machines_lst"

basecmd=$(basename $0)

#########################################################################
# Get the current Locale and determine whether English output is also needed
# Output: LOCALE
#         PRINT_ENG_MSG
#########################################################################
get_current_locale()
{
   # Check if current locale is a English
   LOCALE=`/usr/bin/locale`
   # /usr/bin/locale may produce LC_MESSAGES=en_US or LC_MESSAGES="en_US".
   # We use two sed "s" commands, the first one gets rid of LC_MESSAGES=,
   # the second one removes the two surrounding '"' if they are there.
   LOCALE=`echo "$LOCALE" | grep LC_MESSAGES | sed "s/LC_MESSAGES=//;s/\"//g"`

   # Do not print English messages if the local language is English.
   # C and POSIX are special locales. Treat them as en_US.
   if [[ "$LOCALE" = "C" || "$LOCALE" = "POSIX" ]]; then
        PRINT_ENG_MSG="NO"
   else
        # A locale may look like en_US or en_US.ISO8859-1. Use cut command
        # to remove the language encoding.
        LOCALE=`echo "$LOCALE" | cut -f 1 -d "."`
        if [[ "$LOCALE" = "en_US" || "$LOCALE" = "En_US" || "$LOCALE" = "en_GB" || "$LOCALE" = "En_GB" ]]
        then
                # Local language is English.
                PRINT_ENG_MSG="NO"
        else
                # Local language is not English (including "$LOCALE"=""),
                # which should not happen in normal cases)
                PRINT_ENG_MSG="YES"
        fi
   fi
}

#########################################################################
#                                                                       #
# Function: print_message                                               #
# Description: wrapper for message printing. All messages go to stderr. #
#     For now, all messages are printed in both English and the current #
#     language unless current language is en_US, C, or POSIX.           #
#                                                                       #
#     This subroutine makes it easy to print messages in  either English#
#     or current language or both. Also, it ensure all messages will be #
#     printed to the same stream.                                       #
#########################################################################

print_message()
{
    MSGCMD2="/usr/sbin/rsct/bin/hadspmsg cfgaccess ha_com.cat"
    print -u2 "`${MSGCMD2} $*`"

    if [[ $PRINT_ENG_MSG = "YES" ]]
    then
        print -u2 "`LC_ALL=en_US ${MSGCMD2} $*`"
    fi
}


#
function print_dbgmsg
{
   if [[ -n $HA_CCAL_LOG ]]; then
	print `date` ${basecmd}: "$*" >> $HA_CCAL_LOG
   fi
}

#

#***************************************************************************=
RSCTGRP=rsct
RMGRP=rsct_rm

# create the initial 'cluster info' when rmc is not installed
# INPUT: cluster_name node_number 
function create_cluster_info_files
{
   clustername=$1	# cluster_name
   nodenum=$2		# node number
   print_dbgmsg "create cluster=$clustername node=$nodenum"
   if [[ -a $CTROOT/$clustername ]]; then
	print_dbgmsg "cluster $clustername already exists"
	return 1;
   fi

   if [[ $(uname -s) = "AIX" ]]; then
	LC_ALL=C uname -x | read r1 r2 MID junk
   else
	MID=$(uuidgen)
   fi

   # create directories, using the machine ID as the cluster ID
   for name in $CTROOT/cfg \
		$CTROOT/$MID $CTROOT/$MID/cfg  \
		$CTROOT/$MID/lck $CTROOT/$MID/log \
		$CTROOT/$MID/run $CTROOT/$MID/soc
   do
        if [[ ! -a $name ]]; then
                if  mkdir $name
                then
                	chown bin $name
                	chgrp bin $name
                	chmod 775 $name
		fi
        fi
   done

   # link the cluster name
   ln -f -s $CTROOT/$MID $CTROOT/$clustername

   # add this cluster to cluster list file
   print "$MID $clustername" >> $CTROOT/cfg/clusters

   print "$MID" > $CTROOT/cfg/default_cluster
   print "$MID" > $CTROOT/cfg/current_cluster

   print "$nodenum $MID localhost $MID $clustername $nodenum" \
	> $CTROOT/$clustername/cfg/nodedef.cfg

   print_dbgmsg "cluster info creation is done"

   return 0
}

#
# Wait rmc procs to be stopped, and cleanup SR
# Restart RMC procs as the fresh daemons
# (This function may be called in concurrent mode)
function restart_rmc_procs 
{
    print_dbgmsg "restart_rmc_procs"

    if [[ -x ${RSCTBIN}/rmcctrl ]]; then
	# stop RMC & RMs
	${RSCTBIN}/rmcctrl -z
   	print_dbgmsg "rmc_procs stopped"

	# Reinsert and start RMC 
	${RSCTBIN}/rmcctrl -A
    fi

    print_dbgmsg "rmc_procs restarted"
    return 0
}

#
# This function may be called in non-ConfigRM environments(e.g., GPFS)
# input: clstname nodenum
function rsct_basic_change_cluster_name
{
    #
    CLSTNAME=$1
    NODENUM=$2

    # If clstname or nodenumber is nil, return error
    if [[ -z $CLSTNAME || -z $NODENUM ]]; then
        print_message IMSG_cfghact_Usage $basecmd
	exit 1;
    fi
    
    #
    print_dbgmsg "cfghact CLST=$CLSTNAME NODE=$NODENUM"
    
    #
    # Know whether there is a change 
    # about clstname, number, or current_cluster
    umask 022
    
    #
    # If the desired cluster info does not exist,
    # create the cluster info
    clinfo_changed=0
    if [[ ! -a $CTROOT/$CLSTNAME ]]; then
	create_cluster_info_files $CLSTNAME $NODENUM
	clinfo_changed=1
    fi
    
    # exit if current_cluster info does not exist
    if [[ ! -a $CTROOT/cfg/current_cluster ]]; then
        print_message EMSG104 $basecmd $CTROOT/cfg/current_cluster
	exit 1
    fi
    
    # Get the new cluster info
    NODEDEF_CFG=$CTROOT/$CLSTNAME/cfg/nodedef.cfg
    if [[ -z $NODEDEF_CFG || ! -a ${NODEDEF_CFG} ]]; then
	# node definition file does not exist. 
	print_message EMSG104 $basecmd $NODEDEF_CFG 
	exit 1
    fi
    
    # get the given cluster id & name
    CLSTID=$(grep -w "$CLSTNAME" $CTROOT/cfg/clusters | awk '{print $1}')
    print_dbgmsg "GIVEN CLID=$CTSTID NAME=$CLSTNAME"
    
    # switch the current cluster to new cluster
    set -A CURCLID $(cat $CTROOT/cfg/current_cluster)
    CURCLNAME=$(grep -w "$CURCLID" $CTROOT/cfg/clusters | awk '{print $2}')
    print_dbgmsg "CURRENT CURCLID=$CURCLID CURCLNAME=$CURCLNAME"
    if [[ $CURCLNAME != $CLSTNAME ]]; then
	clinfo_changed=1
    fi
    
    # Check the node number whether they are same
    # if node number is different, update nodedef.cfg
    # and restart RMC/RM subsystems
    #
    # get the current cluster info (as well as old node#)
    set -A clinfo $(cat ${NODEDEF_CFG})
    old_nodenum=${clinfo[0]}        # node number
    old_nodename=${clinfo[2]}       # hostname
    old_clstid=${clinfo[3]}         # clst-id
    old_clstname=${clinfo[4]}       # cluster name
    
    if [[ $old_nodenum != $NODENUM ]]; then
	clinfo_changed=1
	# Replace <NODEDEF_CFG> file with the new node number
	print $NODENUM $old_clstid $old_nodename $old_clstid \
		$CLSTNAME $NODENUM > $NODEDEF_CFG
    fi
    
    #change current_cluster and default_cluster
    if [[ $clinfo_changed -ne 0 ]]; then
	print_dbgmsg "Set the current to $CLSTID, $CLSTNAME, $NODENUM"
	print "$CLSTID" > $CTROOT/cfg/current_cluster
    fi

    # update the default cluster
    set -A DEFCLID $(cat $CTROOT/cfg/default_cluster)
    if [[ ! -a $CTROOT/cfg/default_cluster  || $CLSTID != $DEFCLID ]]; then
	print "$CLSTID" > $CTROOT/cfg/default_cluster
    fi
    
    print_dbgmsg "Current setup ($CLSTID $CLSTNAME $NODENUM) successfully"

    return 0	# success
}

#
# This function will be called BEFORE upgrade
#
function rsct_basic_pre_upgrade
{
    # Always stop all resource managers and the rmc daemon
    if [[ -x ${RSCTBIN}/rmcctrl ]]
    then
	${RSCTBIN}/rmcctrl -z
        rc=$?
        if [[ $rc -ne 0 ]]
        then
            print_message IMSG_Warning_1
        fi
    fi

    # (Upgrade) At this momement, ConfigRM should already be stopped.
    # Now time to stop HATS/HATS too if they are running
    if [[ -x ${RSCTBIN}/cthagsctrl ]]; then
	${RSCTBIN}/cthagsctrl -k
    fi
    if [[ -x ${RSCTBIN}/cthatsctrl ]]; then
	${RSCTBIN}/cthatsctrl -k
    fi

    return 0	# success
}

#
function rsct_basic_post_install_or_upgrade
{
    # Link CCAL scripts to cfgmgr if not done already
    for name in ${CCAL_CMDS}
    do
	srcname=${RSCTBIN}/cfgmgr/$name
	tgtname=${RSCTBIN}/$name
	if [[ ! -a $tgtname ]]
	then
		ln -fs $srcname $tgtname
	fi
    done

    if [[ -n $NO_RESTART && $NO_RESTART -eq 1 ]]; then
	# Do not need to proceed...
	return 0
    fi
    
    # Re-add RMC subsystem which will rebuild CDB if necessary
    if [[ -z "$NO_RESTART" && -x ${RSCTBIN}/rmcctrl ]]
    then
	${RSCTBIN}/rmcctrl -A
	rc=$?
	if [[ $rc -ne 0 ]]
	then
            print_message IMSG_Warning_2 $rc
	fi

	# enable the remote connections
	${RSCTBIN}/rmcctrl -p
    fi

    # NOTE: HATS/HAGS should be started if non-IW && non-cfgmgr
    if [[ -f ${RSCTBIN}/ct_clusterinfo ]]; then
	clname=`${RSCTBIN}/ct_clusterinfo -c 2> /dev/null`
    fi
    if [[ -z ${clname} ]]; then
	clname=IW       # assume IW mode
    fi

    if [[ -x ${RSCTBIN}/ct_hats_info ]]; then
	ClstEnv=$(${RSCTBIN}/ct_hats_info 2> /dev/null | \
			grep ENVIRONMENT | awk '{print $2}')
    fi
    if [[ -z ${ClstEnv} ]]; then
	ClstEnv="cfgmgr"        # assume it is under cfgmgr
    fi

    if [[ X${clname}X != XIWX && X${ClstEnv}X != XcfgmgrX ]]; then
	# 
	# start HATS/HAGS if necessary
	if [[ -x ${RSCTBIN}/cthatsctrl ]]; then
	     LC_ALL=C lssrc -s cthats > /dev/null 2>&1
	     if [[ $? -eq 0 ]]; then
		# cthats is installed
		${RSCTBIN}/cthatsctrl -s
	     fi
	fi
	if [[ -x ${RSCTBIN}/cthagsctrl ]]; then
	     LC_ALL=C lssrc -s cthags > /dev/null 2>&1
	     if [[ $? -eq 0 ]]; then
		# cthags is installed
		${RSCTBIN}/cthagsctrl -s
             fi
	fi
    fi

    return 0	# success
}

#-----pre-uninstall-------------------
# This function will be called BEFORE upgrade
# Input: -z: uninstall
#        -d: delete subsystems
function rsct_basic_pre_uninst_unupd_delsys
{
    HOW=$1	# one of -d, -z
    # cleanup if ENVIRONMENT is not "cfgmgr"
    if [[ -x ${RSCTBIN}/ct_hats_info ]]; then
	ClstEnv=$(${RSCTBIN}/ct_hats_info 2> /dev/null | \
			grep ENVIRONMENT | awk '{print $2}')
    fi
    if [[ -z ${ClstEnv} ]]; then
	ClstEnv="cfgmgr"
    fi


    # This node must be offline----------------
    if [[ ${ClstEnv} = "cfgmgr" ]]; then
	if [[ -f ${RSCTBIN}/ct_clusterinfo ]]; then
		clname=`${RSCTBIN}/ct_clusterinfo -c 2> /dev/null`
	fi
	if [[ -z ${clname} ]]; then
		clname=IW       # assume IW mode
	fi

	if [[ -n ${clname} && ${clname} != "IW" && -x ${RSCTBIN}/stoprpnode ]]; then
	    MYID=$(LC_ALL=C ${RSCTBIN}/lsnodeid)
	    MYNAME=$(LC_ALL=C lsrsrc -p0 -t -x -s "NodeIDs={0x$MYID}" IBM.PeerNode Name | tr '\"' " ")
	    if [[ -n $MYNAME ]]; then
		${RSCTBIN}/stoprpnode $MYNAME 2> /dev/null
		# wait till cluster name becomes "IW"
                (( i = 30 ))
                while (( $i > 0 ))
                do
			clname=$(${RSCTBIN}/ct_clusterinfo -c 2> /dev/null)
                        if [[ -z $clname || $clname = "IW" ]]; then
                                break
                        else
                                sleep 2
                                (( i = $i - 2 ))
                        fi
                done
	    fi
	fi
    fi

    # Always stop all resource managers and the rmc daemon
    if [[ -x ${RSCTBIN}/rmcctrl ]]
    then
	${RSCTBIN}/rmcctrl -z
        rc=$?
        if [[ $rc -ne 0 ]]
        then
            print_message IMSG_Warning_1
	    #exit an error condition
	    exit $rc
        fi
    fi

    # (Uninstall) At this momement, ConfigRM should already be stopped.
    # Now time to stop HATS/HATS too if they are running
    if [[ -z "${HOW}" ]]; then
	HOW="-k"
    fi
    if [[ -x ${RSCTBIN}/cthagsctrl ]]; then
	${RSCTBIN}/cthagsctrl -k
	if [[ $HOW != "-k" ]]; then
		${RSCTBIN}/cthagsctrl ${HOW}
	fi
    fi
    if [[ -x ${RSCTBIN}/cthatsctrl ]]; then
	${RSCTBIN}/cthatsctrl -k
	if [[ $HOW != "-k" ]]; then
		$RSCTBIN/cthatsctrl ${HOW}
	fi
    fi

    if [[ ${ClstEnv} != "cfgmgr" ]]; then
	# for NON-cfgmgr
	# Change the cluster name to "IW" & Node=1
	rsct_basic_change_cluster_name IW 1

	# unlink the symbolic links which were created at (-i) time,
	# and relink them to "cfgmgr" CCAL so that ConfigRM can use them
	for name in ${CCAL_CMDS}
	do
           if [[ -a ${RSCTBIN}/$name ]]; then
               rm -f ${RSCTBIN}/$name
               ln -fs /usr/sbin/rsct/cfgmgr/$name ${RSCTBIN}/$name
           fi
       done

    fi

    return 0
}


#
# main function starts ----------------------------------
#

print_dbgmsg "$* called"

get_current_locale

# parse the arguments
FORCEFLAG=0
WAITRMC=0
NO_RESTART=""
OPCMD=""
Argcount=0
while getopts ":c:n:fwiKUuzdx" opt
do
    case $opt in
	u )	OPCMD=postupgrade;	Argcount=$((Argcount+1));;
	i )	OPCMD=postinstall;	Argcount=$((Argcount+1));;
	U )	OPCMD=preupgrade;	Argcount=$((Argcount+1));;
	U )	OPCMD=preupgrade;	Argcount=$((Argcount+1));;
	z )	OPCMD=predeinstall;	Argcount=$((Argcount+1));;
	d )	OPCMD=delsubsys;	Argcount=$((Argcount+1));;
	c )     OPCMD=change;		Argcount=$((Argcount+1));
		CLSTNAME=$OPTARG;;      # cluster name
	n )     NODENUM=$OPTARG;;    # node number
	f )	FORCEFLAG=1;;		#force RMC
	x )	NO_RESTART=1;;	#network_install
	w )	WAITRMC=1;;		# (sync) wait till RMC done
        h )     print_message IMSG_cfghact_Usage $basecmd
                exit 0;;
        ? ) print_message EMSG100 $basecmd $OPTARG
                exit 1;;
    esac
done

if ((Argcount == 0))
then
        # no argument specified
        print_message EMSG101 $basecmd 
        print_message IMSG_cfghact_Usage $basecmd
	exit 1
fi

if ((Argcount > 1))
then
        # More than one argument specified 
        print_message EMSG102 $basecmd 
        print_message IMSG_cfghact_Usage $basecmd
	exit 1
fi

rc=0
case $OPCMD in
    preupgrade )
	rsct_basic_pre_upgrade
	exit $?
	;;

    delsubsys )
        LC_ALL=C lssrc -s ctrmc > /dev/null 2>&1
        rmc_not_installed=$?        # rmc installed?

	rsct_basic_pre_uninst_unupd_delsys  -d
	rc=$?
        if [[ -z $NO_RESTART || $NO_RESTART -eq 0 ]]; then
		if [[ $rmc_not_installed -eq 0 ]]; then
			restart_rmc_procs
		fi
        fi
	exit $rc
	;;

    predeinstall )
        LC_ALL=C lssrc -s ctrmc > /dev/null 2>&1
        rmc_not_installed=$?        # rmc installed?

	rsct_basic_pre_uninst_unupd_delsys  -z
	rc=$?
        if [[ -z $NO_RESTART || $NO_RESTART -eq 0 ]]; then
		if [[ $rmc_not_installed -eq 0 ]]; then
			restart_rmc_procs
		fi
        fi
	exit $rc
	;;

    postinstall | postupgrade )
	if [[ $FORCEFLAG -ne 0 ]]; then
		rsct_basic_pre_upgrade
	fi
	rsct_basic_post_install_or_upgrade
	exit $?
	;;

    change )
	LC_ALL=C lssrc -s ctrmc > /dev/null 2>&1
	rmc_not_installed=$?        # rmc installed?

	rsct_basic_change_cluster_name $CLSTNAME $NODENUM

	# ask to stop rmc
	if [[ $rmc_not_installed -eq 0 ]]; then
	    # Yes RMC is installed.
	    if [[ $FORCEFLAG -ne 0 || $clinfo_changed -ne 0 ]]; then
		# stop and restart rmc procs
		if [[ $WAITRMC -ne 0 ]]; then
			#synchrous
			restart_rmc_procs
		else
			#(CONCURRENTLY)
			restart_rmc_procs &
		fi
	    fi
	fi

	exit $? ;;
esac

exit 0
